#ifndef __GLESDefaultHardwareBufferManager_H__
#define __GLESDefaultHardwareBufferManager_H__

#include "U2GLESPreRequest.h"
#include "U2HardwareBufferManager.h"
#include "U2HardwareVertexBuffer.h"
#include "U2HardwareIndexBuffer.h"


U2EG_NAMESPACE_BEGIN


/// Specialisation of U2HardwareVertexBuffer for emulation
class _U2GLESShare U2GLESDefaultHardwareVertexBuffer : public U2HardwareVertexBuffer
{
protected:
    unsigned char* mpData;
    /** See U2HardwareBuffer. */
    void* lockImpl(size_t offset, size_t length, LockOptions options);
    /** See U2HardwareBuffer. */
    void unlockImpl(void);

public:
    U2GLESDefaultHardwareVertexBuffer(size_t vertexSize, size_t numVertices,
                                    U2HardwareBuffer::Usage usage);
    U2GLESDefaultHardwareVertexBuffer(U2HardwareBufferManagerBase* mgr, size_t vertexSize, size_t numVertices, 
                                    U2HardwareBuffer::Usage usage);
    virtual ~U2GLESDefaultHardwareVertexBuffer();
    /** See U2HardwareBuffer. */
    void readData(size_t offset, size_t length, void* pDest);
    /** See U2HardwareBuffer. */
    void writeData(size_t offset, size_t length, const void* pSource,
                   bool discardWholeBuffer = false);
    /** Override U2HardwareBuffer to turn off all shadowing. */
    void* lock(size_t offset, size_t length, LockOptions options);
    /** Override U2HardwareBuffer to turn off all shadowing. */
    void unlock(void);

    void* getDataPtr(size_t offset) const { return (void*)(mpData + offset); }
};



/// Specialisation of U2HardwareIndexBuffer for emulation
class _U2GLESShare U2GLESDefaultHardwareIndexBuffer : public U2HardwareIndexBuffer
{
protected:
    unsigned char* mpData;
    /** See U2HardwareBuffer. */
    void* lockImpl(size_t offset, size_t length, LockOptions options);
    /** See U2HardwareBuffer. */
    void unlockImpl(void);

public:
    U2GLESDefaultHardwareIndexBuffer(IndexType idxType, size_t numIndexes, U2HardwareBuffer::Usage usage);
    virtual ~U2GLESDefaultHardwareIndexBuffer();
    /** See U2HardwareBuffer. */
    void readData(size_t offset, size_t length, void* pDest);
    /** See U2HardwareBuffer. */
    void writeData(size_t offset, size_t length, const void* pSource,
            bool discardWholeBuffer = false);
    /** Override U2HardwareBuffer to turn off all shadowing. */
    void* lock(size_t offset, size_t length, LockOptions options);
    /** Override U2HardwareBuffer to turn off all shadowing. */
    void unlock(void);

    void* getDataPtr(size_t offset) const { return (void*)(mpData + offset); }
};



/** Specialisation of U2HardwareBufferManager to emulate hardware buffers.
@remarks
You might want to instantiate this class if you want to utilise
classes like MeshSerializer without having initialised the 
rendering system (which is required to create a 'real' hardware
buffer manager.
*/
class _U2GLESShare U2GLESDefaultHardwareBufferManagerBase : public U2HardwareBufferManagerBase
{
public:
    U2GLESDefaultHardwareBufferManagerBase();
    virtual ~U2GLESDefaultHardwareBufferManagerBase();
    /// Creates a vertex buffer
    U2HardwareVertexBufferSharedPtr
        createVertexBuffer(size_t vertexSize, size_t numVerts,
            U2HardwareBuffer::Usage usage, bool useShadowBuffer = false);
    /// Create a hardware vertex buffer
    U2HardwareIndexBufferSharedPtr
        createIndexBuffer(U2HardwareIndexBuffer::IndexType itype, size_t numIndexes,
            U2HardwareBuffer::Usage usage, bool useShadowBuffer = false);
};



/// GLESDefaultHardwareBufferManagerBase as a Singleton
class _U2GLESShare U2GLESDefaultHardwareBufferManager : public U2HardwareBufferManager
{
public:
	U2GLESDefaultHardwareBufferManager()
		: U2HardwareBufferManager(U2_NEW U2GLESDefaultHardwareBufferManagerBase()) 
	{

	}
	~U2GLESDefaultHardwareBufferManager()
	{
		U2_DELETE mImpl;
	}
};

    
U2EG_NAMESPACE_END


#endif
